/*
 * Copyright (C) 2010 TopCoder Inc., All Rights Reserved.
 */
package com.hercules.xre.protocol.testing;

import java.util.List;
import com.topcoder.util.log.Level;
import com.topcoder.util.log.Log;

/**
 * <p>
 * Helper class for this component.
 * </p>
 *
 * <p>
 * <strong>Thread-safety:</strong>This class is immutable and so thread safe.
 * </p>
 *
 * @author TCSDEVELOPER
 * @version 1.0
 */
public final class Helper {
        /**
         * <p>
     * Represents the max valid port.
     * </p>
     */
    private static final int MAX_PORT = 65535;

        /**
     * <p>
     * This private constructor prevents to create a new instance.
     * </p>
     */
    private Helper() {
        // empty
    }
    /**
     * <p>Logs methods entrance info.</p>
     *
     * @param method the method name.
     * @param parameterNames the parameter names array
     * @param parameterValues the parameter values array
     * @param logger the logger to log method entrance.
     */
    public static void logEnter(String method, String[] parameterNames, Object[] parameterValues, Log logger) {
        StringBuilder buffer = new StringBuilder();
        buffer.append("Enter ");
        buffer.append(method);
        if (parameterNames != null) {
            buffer.append(" Input parameters[");
            for (int i = 0; i < parameterNames.length; i++) {
                if (i > 0) {
                    buffer.append(", ");
                }
                buffer.append(parameterNames[i]).append(":").append(parameterValues[i]);
            }
            buffer.append("]");
        }
        logger.log(Level.DEBUG, buffer.toString());
    }

    /**
     * <p>Log method exit with given log and return value.</p>
     *
     * @param logger the logger
     * @param method the method name
     * @param <T> the value type
     * @param value the value
     * @return the value
     */
    public static <T> T logExit(String method, T value, Log logger) {
        StringBuilder sb = new StringBuilder();
        sb.append("Exit ").append(method);
        if (value != null) {
            sb.append(" and return ").append(value);
        }
        logger.log(Level.DEBUG, sb.toString());
        return value;
    }

    /**
     * <p>
     * Checks whether the given Object is null.
     * </p>
     *
     * @param arg the argument to check
     * @param name the name of the argument to check
     * @param methodName the method name
     * @param logger the logger to log method entrance.
     *
     * @throws IllegalArgumentException if the given Object is null
     */
    public static void checkNull(Object arg, String name, String methodName, Log logger) {
        if (arg == null) {
            throw logError(new IllegalArgumentException(
                name + " should not be null"), methodName, logger);
        }
    }

    /**
     * <p>
     * Checks whether the given String is null or empty.
     * </p>
     *
     * @param arg the String to check
     * @param name the name of the String argument to check
     * @param methodName the method name
     * @param logger the logger to log method entrance.
     *
     * @throws IllegalArgumentException if the given string is null or empty (trimmed)
     */
    public static void checkString(String arg, String name, String methodName, Log logger) {
        checkNull(arg, name, methodName, logger);

        if (arg.trim().length() == 0) {
            throw logError(new IllegalArgumentException(
                name + " should not be empty"), methodName, logger);
        }
    }

    /**
     * <p>
     * Checks whether the given String is empty. Notes it can be null.
     * </p>
     *
     * @param arg the String to check
     * @param name the name of the String argument to check
     * @param methodName the method name
     * @param logger the logger to log method entrance.
     *
     * @throws IllegalArgumentException if the given string is null or empty (trimmed)
     */
    public static void checkEmpty(String arg, String name, String methodName, Log logger) {
        if (arg != null) {
            if (arg.trim().length() == 0) {
                throw logError(new IllegalArgumentException(
                    name + " should not be empty"), methodName, logger);
            }
        }
    }

    /**
     * <p>
     * Checks whether the given List is null or empty., or contains null/empty elements.
     * </p>
     *
     * @param arg the list to check
     * @param name the name of the String argument to check
     * @param methodName the method name
     * @param logger the logger to log method entrance.
     *
     * @throws IllegalArgumentException if the given string is null or empty (trimmed)
     */
    public static void checkList(List<String> arg, String name, String methodName, Log logger) {
        checkNull(arg, name, methodName, logger);
        if (arg.size() == 0) {
            throw logError(new IllegalArgumentException(
                name + " should not be empty"), methodName, logger);
        }
        for (int i = 0; i < arg.size(); i++) {
            checkString(arg.get(i), "element in " + name, methodName, logger);
        }
    }

    /**
     * <p>Logs the error message.</p>
     *
     * @param <T> the generic class type of cause
     * @param cause The message caught to be logged.
     * @param methodName the method name
     * @param logger the logger to log method entrance.
     *
     * @return the cause
     */
    public static <T extends Throwable> T logError(T cause, String methodName, Log logger) {
        if (logger != null) {
            String msg = "[" + " Error in method{" + methodName + "}: Details {"
                + cause.getMessage() + "}]";
            logger.log(Level.ERROR, cause, msg);
        }

        return cause;
    }

    /**
     * <p>
     * Logs the method entry and check if the port(first parameter) is valid.
     * </p>
     *
     * @param logger the logger
     * @param method as the method name
     * @param paramNames the parameter names
     * @param paramValues the parameter values
     * @return the valid port
     * @throws IllegalArgumentException if the port < 1 or > 65535
     */
    public static int checkPortAndLog(String method, String[] paramNames,
        Object[] paramValues, Log logger) {
        logEnter(method, paramNames, paramValues, logger);
        int port = (Integer) paramValues[0];
        if (port < 1 || port > MAX_PORT) {
            throw logError(new IllegalArgumentException(
                "the port must in range [1, 65535]"), method, logger);
        }
        return port;
    }
}
